package com.example.lib.c2.pc0;

/**
 * 对象锁
 */
public class Main2ObjectLock {

    private int id = 0;

    public void count() {

        //开两个线程累加为啥结果不是20000
        //++ 是非安全操作
        //每个线程都有自己的工作区域
        //他们会先从主内存中load数据做为一个副本到自己的工作区，然后计算，计算完后把结果刷回主内存中
        //所以在这个计算过程中，如果其他线程load数据，那么该数据就是上个线程计算前的数据，也就是脏数据。
        // 当这个线程计算完把数据刷回主内，很可能把其他线程计算的结果给覆盖了，所以这是一个很不安全的操作
        id++;
    }

    //对象锁
    //这是非静态方法，属于ObjectLock.this的， 所以synchronized 持有属于ObjectLock.this的锁
    public synchronized void count1() {
        //加上 synchronized 对象锁
        id++;
    }

    public void count2() {
        synchronized (Main2ObjectLock.this) {
            id++;
        }
    }

    //随便持有一把锁
    private Object object = new Object();
    public void count3() {
        synchronized (object) {
            id++;
        }
    }

    private static class Count extends Thread {
        private Main2ObjectLock objectLock;

        public Count(Main2ObjectLock objectLock) {
            this.objectLock = objectLock;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10000; i++) {
                objectLock.count(); // 这种结果不会等于20000
//                objectLock.count1();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Main2ObjectLock objectLock = new Main2ObjectLock();
        Count count1 = new Count(objectLock);
        Count count2 = new Count(objectLock);
        count1.start();
        count2.start();

        Thread.sleep(50);
        System.out.println("------" + objectLock.id);
    }
}
